---
title: "Fingerprint Update Strategy"
description: "Automatically prevent incompatible OTA updates by tracking native code changes with Expo's fingerprint library."
icon: Fingerprint
---

import { Tabs, Tab } from 'fumadocs-ui/components/tabs';

## Why Choose Fingerprint?

Fingerprint automatically detects native code changes and blocks incompatible OTA updates. This ensures only safe updates reach your users.

**Fingerprint vs App Version:**
- **Fingerprint**: Automatic protection - detects native changes and blocks unsafe updates
- **App Version**: Manual control - you specify version targets, no automatic checking

Choose Fingerprint for automatic safety. Choose App Version for manual control.

## Setup

Fingerprint is the default strategy. Configure it explicitly if needed:

```typescript title="hot-updater.config.ts"
import { defineConfig } from "hot-updater";

export default defineConfig({
  updateStrategy: "fingerprint", // Default strategy
});
```

### Include Additional Files (Optional)

Track extra files that affect native compatibility:

```typescript title="hot-updater.config.ts"
import { defineConfig } from "hot-updater";

export default defineConfig({
  updateStrategy: "fingerprint",
  fingerprint: {
    extraSources: [
      "config/native-config.json",
      "scripts/post-build.sh",
    ],
    debug: true,
  },
});
```

## Workflow

### Before App Store Submission

**Step 1: Generate Fingerprint**

Before building for App Store, generate the fingerprint:

```package-install
npx hot-updater fingerprint create
```

This creates a `fingerprint.json` file and embeds the hash in your native files:
- iOS: `ios/YourApp/Info.plist`
- Android: `android/app/src/main/res/values/strings.xml`

Example `fingerprint.json`:
```json
{
  "ios": {
    "hash": "11142b9062165fa48665f5efa095dd94e9e45eb0"
  },
  "android": {
    "hash": "c763ed5729a0bcccf23248ee0183ddf9016c2e6e"
  }
}
```

**Step 2: Build and Submit**

Build your app with the embedded fingerprint and submit to the App Store.

**Step 3: Deploy OTA Updates**

After your app is live, deploy JavaScript-only updates:

```package-install
npx hot-updater deploy
```

The system automatically ensures only compatible updates reach users.

### When Native Code Changes

Check if your fingerprint needs updating:

```package-install
npx hot-updater fingerprint
```

If there's a mismatch, create a new fingerprint:

```package-install
npx hot-updater fingerprint create
```

**Important**: After creating a new fingerprint, you must rebuild your app. The new fingerprint must be embedded in the app binary before deploying OTA updates.

## Client Setup

Configure your React Native app:

```tsx title="App.tsx"
import { HotUpdater } from "@hot-updater/react-native";
import { View, Text } from "react-native";

function App() {
  return (
    <View>
      <Text>Hello World</Text>
    </View>
  );
}

export default HotUpdater.wrap({
  baseURL: "https://your-update-server.com/api/update-check", // [!code ++]
  updateStrategy: "fingerprint", // [!code ++]
  updateMode: "auto",
})(App);
```

The client automatically constructs this endpoint:
```
GET {baseUrl}/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleId
```

## How It Works

### JavaScript/UI Changes ✅ OTA Update Safe

```javascript
// ✅ Safe for OTA updates
// - Component logic changes
// - Style and layout updates
// - New screens
// - Business logic changes
// - API call modifications
```

**Result**: Fingerprint unchanged → OTA update deployed

### Native Code Changes ⚠️ Rebuild Required

```bash
# ⚠️ Requires native rebuild
# - New native modules (react-native-camera)
# - React Native version updates
# - Native iOS/Android code changes
# - Build configuration changes
```

**Result**: Fingerprint changed → OTA blocked → Rebuild needed

If you try to deploy with a changed fingerprint:

```bash
$ npx hot-updater deploy
❌ Fingerprint mismatch!
💡 Native code changed. You need to:
1. Run: npx hot-updater fingerprint create
2. Rebuild and resubmit your app
3. Then deploy OTA updates
```

## Advanced

### Multiple App Targets

`fingerprint create` automatically handles standard React Native projects. Only configure custom paths if you have:
- iOS app extensions (widgets, share extensions)
- Multiple Android build variants
- Non-standard project structure

```typescript title="hot-updater.config.ts"
import { defineConfig } from "hot-updater";

export default defineConfig({
  updateStrategy: "fingerprint",
  platform: {
    ios: {
      infoPlistPaths: [
        "ios/YourApp/Info.plist",
        "ios/YourAppWidget/Info.plist",
        "ios/YourAppExtension/Info.plist"
      ]
    },
    android: {
      stringResourcePaths: [
        "android/app/src/main/res/values/strings.xml",
        "android/app/src/debug/res/values/strings.xml"
      ]
    }
  }
});
```

💡 Most projects don't need this - the defaults work perfectly.

### Testing the Endpoint

Test your update endpoint with curl:

```bash
curl "https://your-update-endpoint.com/check-update/fingerprint/ios/11142b9062165fa48665f5efa095dd94e9e45eb0/production/00000000-0000-0000-0000-000000000000/00000000-0000-0000-0000-000000000001"
```

Parameters:
- `:platform` - `ios` or `android`
- `:fingerprintHash` - Current fingerprint hash
- `:channel` - Channel name (e.g., `production`, `staging`)
- `:minBundleId` - Minimum supported bundle ID
- `:bundleId` - Current bundle ID
